home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / UNIXTOOL / GNU / PERL / PERL5SRC.ZIP / !Perl / c / perl < prev    next >
Text File  |  1995-06-28  |  40KB  |  1,789 lines

  1. /*    perl.c
  2.  *
  3.  *    Copyright (c) 1987-1994 Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  */
  9.  
  10. /*
  11.  * "A ship then new they built for him/of mithril and of elven glass" --Bilbo
  12.  */
  13.  
  14. #include "EXTERN.h"
  15. #include "perl.h"
  16. #include "patchlevel.h"
  17.  
  18.  
  19. #ifdef I_UNISTD
  20. #include <unistd.h>
  21. #endif
  22.  
  23.  
  24. char rcsid[] = "perl.c\nPatch level: ###\n";
  25.  
  26. #ifdef IAMSUID
  27. #ifndef DOSUID
  28. #define DOSUID
  29. #endif
  30. #endif
  31.  
  32. #ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
  33. #ifdef DOSUID
  34. #undef DOSUID
  35. #endif
  36. #endif
  37.  
  38. static void find_beginning _((void));
  39. static void incpush _((char *));
  40. static void init_ids _((void));
  41. static void init_debugger _((void));
  42. static void init_lexer _((void));
  43. static void init_main_stash _((void));
  44. static void init_perllib _((void));
  45. static void init_postdump_symbols _((int, char **, char **));
  46. static void init_predump_symbols _((void));
  47. static void init_stacks _((void));
  48. static void open_script _((char *, bool, SV *));
  49. /*
  50. static void validate_suid _((char *));
  51.   scrapped for RISCOS */
  52. PerlInterpreter *
  53. perl_alloc()
  54. {
  55.     PerlInterpreter *sv_interp;
  56.  
  57.     curinterp = 0;
  58.     New(53, sv_interp, 1, PerlInterpreter);
  59.     return sv_interp;
  60. }
  61.  
  62. void
  63. perl_construct( sv_interp )
  64. register PerlInterpreter *sv_interp;
  65. {
  66.     if (!(curinterp = sv_interp))
  67.     return;
  68.  
  69. #ifdef MULTIPLICITY
  70.     Zero(sv_interp, 1, PerlInterpreter);
  71. #endif
  72.  
  73.     /* Init the real globals? */
  74.     if (!linestr) {
  75.     linestr = NEWSV(65,80);
  76.     sv_upgrade(linestr,SVt_PVIV);
  77.  
  78.     SvREADONLY_on(&sv_undef);
  79.  
  80.     sv_setpv(&sv_no,No);
  81.     SvNV(&sv_no);
  82.     SvREADONLY_on(&sv_no);
  83.  
  84.     sv_setpv(&sv_yes,Yes);
  85.     SvNV(&sv_yes);
  86.     SvREADONLY_on(&sv_yes);
  87.  
  88. #ifdef MSDOS
  89.     /*
  90.      * There is no way we can refer to them from Perl so close them to save
  91.      * space.  The other alternative would be to provide STDAUX and STDPRN
  92.      * filehandles.
  93.      */
  94.     (void)fclose(stdaux);
  95.     (void)fclose(stdprn);
  96. #endif
  97.     }
  98.  
  99. #ifdef MULTIPLICITY
  100.     chopset    = " \n-";
  101.     copline    = NOLINE;
  102.     curcop    = &compiling;
  103.     dlmax    = 128;
  104.     laststatval    = -1;
  105.     laststype    = OP_STAT;
  106.     maxscream    = -1;
  107.     maxsysfd    = MAXSYSFD;
  108.     nrs        = "\n";
  109.     nrschar    = '\n';
  110.     nrslen    = 1;
  111.     rs        = "\n";
  112.     rschar    = '\n';
  113.     rsfp    = Nullfp;
  114.     rslen    = 1;
  115.     statname    = Nullsv;
  116.     tmps_floor    = -1;
  117. #endif
  118.  
  119.     init_ids();
  120.     sprintf(patchlevel, "%5.3f", 5.0 + (PATCHLEVEL / 1000.0));
  121.  
  122.     fdpid = newAV();    /* for remembering popen pids by fd */
  123.     pidstatus = newHV();/* for remembering status of dead pids */
  124.  
  125.     init_stacks();
  126.     ENTER;
  127. }
  128.  
  129. void
  130. perl_destruct(sv_interp)
  131. register PerlInterpreter *sv_interp;
  132. {
  133.     int destruct_level;  /* 0=none, 1=full, 2=full with checks */
  134.     I32 last_sv_count;
  135.     HV *hv;
  136.  
  137.     if (!(curinterp = sv_interp))
  138.     return;
  139.  
  140.     destruct_level = perl_destruct_level;
  141.     LEAVE;
  142.     FREETMPS;
  143.  
  144.     if (sv_objcount) {
  145.     /* We must account for everything.  First the syntax tree. */
  146.     if (main_root) {
  147.         curpad = AvARRAY(comppad);
  148.         op_free(main_root);
  149.         main_root = 0;
  150.     }
  151.     }
  152.     if (sv_objcount) {
  153.     /*
  154.      * Try to destruct global references.  We do this first so that the
  155.      * destructors and destructees still exist.  Some sv's might remain.
  156.      * Non-referenced objects are on their own.
  157.      */
  158.  
  159.     dirty = TRUE;
  160.     sv_clean_objs();
  161.     }
  162.  
  163.     if (destruct_level == 0){
  164.  
  165.     DEBUG_P(debprofdump());
  166.  
  167.     /* The exit() function will do everything that needs doing. */
  168.     return;
  169.     }
  170.  
  171.     /* Prepare to destruct main symbol table.  */
  172.     hv = defstash;
  173.     defstash = 0;
  174.     SvREFCNT_dec(hv);
  175.  
  176.     FREETMPS;
  177.     if (destruct_level >= 2) {
  178.     if (scopestack_ix != 0)
  179.         warn("Unbalanced scopes: %d more ENTERs than LEAVEs\n", scopestack_ix);
  180.     if (savestack_ix != 0)
  181.         warn("Unbalanced saves: %d more saves than restores\n", savestack_ix);
  182.     if (tmps_floor != -1)
  183.         warn("Unbalanced tmps: %d more allocs than frees\n", tmps_floor + 1);
  184.     if (cxstack_ix != -1)
  185.         warn("Unbalanced context: %d more PUSHes than POPs\n", cxstack_ix + 1);
  186.     }
  187.  
  188.     /* Now absolutely destruct everything, somehow or other, loops or no. */
  189.     last_sv_count = 0;
  190.     while (sv_count != 0 && sv_count != last_sv_count) {
  191.     last_sv_count = sv_count;
  192.     sv_clean_all();
  193.     }
  194.     if (sv_count != 0)
  195.     warn("Scalars leaked: %d\n", sv_count);
  196.  
  197.     DEBUG_P(debprofdump());
  198. }
  199.  
  200. void
  201. perl_free(sv_interp)
  202. PerlInterpreter *sv_interp;
  203. {
  204.     if (!(curinterp = sv_interp))
  205.     return;
  206.     Safefree(sv_interp);
  207. }
  208. #if !defined(STANDARD_C) && !defined(HAS_GETENV_PROTOTYPE)
  209. char *getenv _((char *)); /* Usually in <stdlib.h> */
  210. #endif
  211.  
  212. int
  213. perl_parse(sv_interp, xsinit, argc, argv, env)
  214. PerlInterpreter *sv_interp;
  215. void (*xsinit)_((void));
  216. int argc;
  217. char **argv;
  218. char **env;
  219. {
  220.     register SV *sv;
  221.     register char *s;
  222.     char *scriptname;
  223.     VOL bool dosearch = FALSE;
  224.     char *validarg = "";
  225.     AV* comppadlist;
  226.  
  227. #ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
  228. #ifdef IAMSUID
  229. #undef IAMSUID
  230.     croak("suidperl is no longer needed since the kernel can now execute\n\
  231. setuid perl scripts securely.\n");
  232. #endif
  233. #endif
  234.  
  235.     if (!(curinterp = sv_interp))
  236.     return 255;
  237.  
  238.     origargv = argv;
  239.     origargc = argc;
  240. #if !defined(VMS) && !defined(RISCOS)  /* VMS doesn't have environ array */
  241.     origenviron = environ;
  242. #endif
  243.  
  244.     if (do_undump) {
  245.  
  246.     /* Come here if running an undumped a.out. */
  247.  
  248.     origfilename = savepv(argv[0]);
  249.     do_undump = FALSE;
  250.     cxstack_ix = -1;        /* start label stack again */
  251.     init_ids();
  252.     init_postdump_symbols(argc,argv,env);
  253.     return 0;
  254.     }
  255.  
  256.     if (main_root)
  257.     op_free(main_root);
  258.     main_root = 0;
  259.  
  260.     switch (setjmp(top_env)) {
  261.     case 1:
  262. #ifdef VMS
  263.     statusvalue = 255;
  264. #else
  265.     statusvalue = 1;
  266. #endif
  267.     case 2:
  268.     curstash = defstash;
  269.     if (endav)
  270.         calllist(endav);
  271.     return(statusvalue);    /* my_exit() was called */
  272.     case 3:
  273.     fprintf(stderr, "panic: top_env\n");
  274.     return 1;
  275.     }
  276.  
  277.     sv_setpvn(linestr,"",0);
  278.     sv = newSVpv("",0);        /* first used for -I flags */
  279.     SAVEFREESV(sv);
  280.     init_main_stash();
  281.     for (argc--,argv++; argc > 0; argc--,argv++) {
  282.     if (argv[0][0] != '-' || !argv[0][1])
  283.         break;
  284. #ifdef DOSUID
  285.     if (*validarg)
  286.     validarg = " PHOOEY ";
  287.     else
  288.     validarg = argv[0];
  289. #endif
  290.     s = argv[0]+1;
  291.       reswitch:
  292.     switch (*s) {
  293.     case '0':
  294.     case 'F':
  295.     case 'a':
  296.     case 'c':
  297.     case 'd':
  298.     case 'D':
  299.     case 'i':
  300.     case 'l':
  301.     case 'n':
  302.     case 'p':
  303.     case 's':
  304.     case 'T':
  305.     case 'u':
  306.     case 'U':
  307.     case 'v':
  308.     case 'w':
  309.         if (s = moreswitches(s))
  310.         goto reswitch;
  311.         break;
  312.  
  313.     case 'e':
  314.         if (euid != uid || egid != gid)
  315.         croak("No -e allowed in setuid scripts");
  316.         if (!e_fp) {
  317.             e_tmpname = savepv(TMPPATH);
  318.         (void)mktemp(e_tmpname);
  319.         if (!*e_tmpname)
  320.             croak("Can't mktemp()");
  321.         e_fp = fopen(e_tmpname,"w");
  322.         if (!e_fp)
  323.             croak("Cannot open temporary file");
  324.         }
  325.         if (argv[1]) {
  326.         fputs(argv[1],e_fp);
  327.         argc--,argv++;
  328.         }
  329.         (void)putc('\n', e_fp);
  330.         break;
  331.     case 'I':
  332.         taint_not("-I");
  333.         sv_catpv(sv,"-");
  334.         sv_catpv(sv,s);
  335.         sv_catpv(sv," ");
  336.         if (*++s) {
  337.         av_push(GvAVn(incgv),newSVpv(s,0));
  338.         }
  339.         else if (argv[1]) {
  340.         av_push(GvAVn(incgv),newSVpv(argv[1],0));
  341.         sv_catpv(sv,argv[1]);
  342.         argc--,argv++;
  343.         sv_catpv(sv," ");
  344.         }
  345.         break;
  346.     case 'P':
  347.         taint_not("-P");
  348.         preprocess = TRUE;
  349.         s++;
  350.         goto reswitch;
  351.     case 'S':
  352.         taint_not("-S");
  353.         dosearch = TRUE;
  354.         s++;
  355.         goto reswitch;
  356.     case 'x':
  357.         doextract = TRUE;
  358.         s++;
  359.         if (*s)
  360.         cddir = savepv(s);
  361.         break;
  362.     case '-':
  363.         argc--,argv++;
  364.         goto switch_end;
  365.     case 0:
  366.         break;
  367.     default:
  368.         croak("Unrecognized switch: -%s",s);
  369.     }
  370.     }
  371.   switch_end:
  372.     scriptname = argv[0];
  373.     if (e_fp) {
  374.     if (fflush(e_fp) || ferror(e_fp) || fclose(e_fp))
  375.         croak("Can't write to temp file for -e: %s", Strerror(errno));
  376.     argc++,argv--;
  377.     scriptname = e_tmpname;
  378.     }
  379.     else if (scriptname == Nullch) {
  380. #ifdef MSDOS
  381.     if ( isatty(fileno(stdin)) )
  382.         moreswitches("v");
  383. #endif
  384.     scriptname = "-";
  385.     }
  386.  
  387.     init_perllib();
  388.  
  389.     open_script(scriptname,dosearch,sv);
  390. #ifndef RISCOS
  391.     validate_suid(validarg);
  392. #endif
  393.  
  394.     if (doextract)
  395.     find_beginning();
  396.  
  397.     compcv = (CV*)NEWSV(1104,0);
  398.     sv_upgrade((SV *)compcv, SVt_PVCV);
  399.  
  400.     pad = newAV();
  401.     comppad = pad;
  402.     av_push(comppad, Nullsv);
  403.     curpad = AvARRAY(comppad);
  404.     padname = newAV();
  405.     comppad_name = padname;
  406.     comppad_name_fill = 0;
  407.     min_intro_pending = 0;
  408.     padix = 0;
  409.  
  410.     comppadlist = newAV();
  411.     AvREAL_off(comppadlist);
  412.     av_store(comppadlist, 0, SvREFCNT_inc((SV*)comppad_name));
  413.     av_store(comppadlist, 1, SvREFCNT_inc((SV*)comppad));
  414.     CvPADLIST(compcv) = comppadlist;
  415.  
  416.     if (xsinit)
  417.     (*xsinit)();    /* in case linked C routines want magical variables */
  418. #ifdef VMS
  419.     init_os_extras();
  420. #endif
  421.  
  422.     init_predump_symbols();
  423.     if (!do_undump)
  424.     init_postdump_symbols(argc,argv,env);
  425.  
  426.     init_lexer();
  427.  
  428.     /* now parse the script */
  429.  
  430.     error_count = 0;
  431.     if (yyparse() || error_count) {
  432.     if (minus_c)
  433.         croak("%s had compilation errors.\n", origfilename);
  434.     else {
  435.         croak("Execution of %s aborted due to compilation errors.\n",
  436.         origfilename);
  437.     }
  438.     }
  439.     curcop->cop_line = 0;
  440.     curstash = defstash;
  441.     preprocess = FALSE;
  442.     if (e_fp) {
  443.     e_fp = Nullfp;
  444.     (void)UNLINK(e_tmpname);
  445.     }
  446.  
  447.     /* now that script is parsed, we can modify record separator */
  448.  
  449.     rs = nrs;
  450.     rslen = nrslen;
  451.     rschar = nrschar;
  452.     rspara = (nrslen == 2);
  453.     sv_setpvn(GvSV(gv_fetchpv("/", TRUE, SVt_PV)), rs, rslen);
  454.  
  455.     if (do_undump)
  456.     my_unexec();
  457.  
  458.     if (dowarn)
  459.     gv_check(defstash);
  460.  
  461.     LEAVE;
  462.     FREETMPS;
  463.     ENTER;
  464.     restartop = 0;
  465.     return 0;
  466. }
  467.  
  468. int
  469. perl_run(sv_interp)
  470. PerlInterpreter *sv_interp;
  471. {
  472.     if (!(curinterp = sv_interp))
  473.     return 255;
  474.     switch (setjmp(top_env)) {
  475.     case 1:
  476.     cxstack_ix = -1;        /* start context stack again */
  477.     break;
  478.     case 2:
  479.     curstash = defstash;
  480.     if (endav)
  481.         calllist(endav);
  482.     FREETMPS;
  483.     return(statusvalue);        /* my_exit() was called */
  484.     case 3:
  485.     if (!restartop) {
  486.         fprintf(stderr, "panic: restartop\n");
  487.         FREETMPS;
  488.         return 1;
  489.     }
  490.     if (stack != mainstack) {
  491.         dSP;
  492.         SWITCHSTACK(stack, mainstack);
  493.     }
  494.     break;
  495.     }
  496.  
  497.     if (!restartop) {
  498.     DEBUG_x(dump_all());
  499.     DEBUG(fprintf(stderr,"\nEXECUTING...\n\n"));
  500.  
  501.     if (minus_c) {
  502.         fprintf(stderr,"%s syntax OK\n", origfilename);
  503.         my_exit(0);
  504.     }
  505.     if (perldb && DBsingle)
  506.        sv_setiv(DBsingle, 1);
  507.     }
  508.  
  509.     /* do it */
  510.  
  511.     if (restartop) {
  512.     op = restartop;
  513.     restartop = 0;
  514.     run();
  515.     }
  516.     else if (main_start) {
  517.     op = main_start;
  518.     run();
  519.     }
  520.  
  521.     my_exit(0);
  522.     return 0;
  523. }
  524.  
  525. void
  526. my_exit(status)
  527. U32 status;
  528. {
  529.     register CONTEXT *cx;
  530.     I32 gimme;
  531.     SV **newsp;
  532.  
  533.     statusvalue = FIXSTATUS(status);
  534.     if (cxstack_ix >= 0) {
  535.     if (cxstack_ix > 0)
  536.         dounwind(0);
  537.     POPBLOCK(cx,curpm);
  538.     LEAVE;
  539.     }
  540.     longjmp(top_env, 2);
  541. }
  542.  
  543. SV*
  544. perl_get_sv(name, create)
  545. char* name;
  546. I32 create;
  547. {
  548.     GV* gv = gv_fetchpv(name, create, SVt_PV);
  549.     if (gv)
  550.     return GvSV(gv);
  551.     return Nullsv;
  552. }
  553.  
  554. AV*
  555. perl_get_av(name, create)
  556. char* name;
  557. I32 create;
  558. {
  559.     GV* gv = gv_fetchpv(name, create, SVt_PVAV);
  560.     if (create)
  561.         return GvAVn(gv);
  562.     if (gv)
  563.     return GvAV(gv);
  564.     return Nullav;
  565. }
  566.  
  567. HV*
  568. perl_get_hv(name, create)
  569. char* name;
  570. I32 create;
  571. {
  572.     GV* gv = gv_fetchpv(name, create, SVt_PVHV);
  573.     if (create)
  574.         return GvHVn(gv);
  575.     if (gv)
  576.     return GvHV(gv);
  577.     return Nullhv;
  578. }
  579.  
  580. CV*
  581. perl_get_cv(name, create)
  582. char* name;
  583. I32 create;
  584. {
  585.     GV* gv = gv_fetchpv(name, create, SVt_PVCV);
  586.     if (create && !GvCV(gv))
  587.         return newSUB(start_subparse(),
  588.               newSVOP(OP_CONST, 0, newSVpv(name,0)),
  589.               Nullop);
  590.     if (gv)
  591.     return GvCV(gv);
  592.     return Nullcv;
  593. }
  594.  
  595. /* Be sure to refetch the stack pointer after calling these routines. */
  596.  
  597. I32
  598. perl_call_argv(subname, flags, argv)
  599. char *subname;
  600. I32 flags;        /* See G_* flags in cop.h */
  601. register char **argv;    /* null terminated arg list */
  602. {
  603.     dSP;
  604.  
  605.     PUSHMARK(sp);
  606.     if (argv) {
  607.     while (*argv) {
  608.         XPUSHs(sv_2mortal(newSVpv(*argv,0)));
  609.         argv++;
  610.     }
  611.     PUTBACK;
  612.     }
  613.     return perl_call_pv(subname, flags);
  614. }
  615.  
  616. I32
  617. perl_call_pv(subname, flags)
  618. char *subname;        /* name of the subroutine */
  619. I32 flags;        /* See G_* flags in cop.h */
  620. {
  621.     return perl_call_sv((SV*)perl_get_cv(subname, TRUE), flags);
  622. }
  623.  
  624. I32
  625. perl_call_method(methname, flags)
  626. char *methname;        /* name of the subroutine */
  627. I32 flags;        /* See G_* flags in cop.h */
  628. {
  629.     dSP;
  630.     OP myop;
  631.     if (!op)
  632.     op = &myop;
  633.     XPUSHs(sv_2mortal(newSVpv(methname,0)));
  634.     PUTBACK;
  635.     pp_method();
  636.     return perl_call_sv(*stack_sp--, flags);
  637. }
  638.  
  639. /* May be called with any of a CV, a GV, or an SV containing the name. */
  640. I32
  641. perl_call_sv(sv, flags)
  642. SV* sv;
  643. I32 flags;        /* See G_* flags in cop.h */
  644. {
  645.     LOGOP myop;        /* fake syntax tree node */
  646.     SV** sp = stack_sp;
  647.     I32 oldmark = TOPMARK;
  648.     I32 retval;
  649.     jmp_buf oldtop;
  650.     I32 oldscope;
  651.  
  652.     if (flags & G_DISCARD) {
  653.     ENTER;
  654.     SAVETMPS;
  655.     }
  656.  
  657.     SAVESPTR(op);
  658.     op = (OP*)&myop;
  659.     Zero(op, 1, LOGOP);
  660.     EXTEND(stack_sp, 1);
  661.     *++stack_sp = sv;
  662.     oldscope = scopestack_ix;
  663.  
  664.     if (!(flags & G_NOARGS))
  665.     myop.op_flags = OPf_STACKED;
  666.     myop.op_next = Nullop;
  667.     myop.op_flags |= OPf_KNOW;
  668.     if (flags & G_ARRAY)
  669.       myop.op_flags |= OPf_LIST;
  670.  
  671.     if (flags & G_EVAL) {
  672.     Copy(top_env, oldtop, 1, jmp_buf);
  673.  
  674.     cLOGOP->op_other = op;
  675.     markstack_ptr--;
  676.     pp_entertry();
  677.     markstack_ptr++;
  678.  
  679.     restart:
  680.     switch (setjmp(top_env)) {
  681.     case 0:
  682.         break;
  683.     case 1:
  684. #ifdef VMS
  685.         statusvalue = 255;    /* XXX I don't think we use 1 anymore. */
  686. #else
  687.     statusvalue = 1;
  688. #endif
  689.         /* FALL THROUGH */
  690.     case 2:
  691.         /* my_exit() was called */
  692.         curstash = defstash;
  693.         FREETMPS;
  694.         Copy(oldtop, top_env, 1, jmp_buf);
  695.         if (statusvalue)
  696.         croak("Callback called exit");
  697.         my_exit(statusvalue);
  698.         /* NOTREACHED */
  699.     case 3:
  700.         if (restartop) {
  701.         op = restartop;
  702.         restartop = 0;
  703.         goto restart;
  704.         }
  705.         stack_sp = stack_base + oldmark;
  706.         if (flags & G_ARRAY)
  707.         retval = 0;
  708.         else {
  709.         retval = 1;
  710.         *++stack_sp = &sv_undef;
  711.         }
  712.         goto cleanup;
  713.     }
  714.     }
  715.  
  716.     if (op == (OP*)&myop)
  717.     op = pp_entersub();
  718.     if (op)
  719.     run();
  720.     retval = stack_sp - (stack_base + oldmark);
  721.     if (flags & G_EVAL)
  722.     sv_setpv(GvSV(gv_fetchpv("@",TRUE, SVt_PV)),"");
  723.  
  724.   cleanup:
  725.     if (flags & G_EVAL) {
  726.     if (scopestack_ix > oldscope) {
  727.         SV **newsp;
  728.         PMOP *newpm;
  729.         I32 gimme;
  730.         register CONTEXT *cx;
  731.         I32 optype;
  732.  
  733.         POPBLOCK(cx,newpm);
  734.         POPEVAL(cx);
  735.         pop_return();
  736.         curpm = newpm;
  737.         LEAVE;
  738.     }
  739.     Copy(oldtop, top_env, 1, jmp_buf);
  740.     }
  741.     if (flags & G_DISCARD) {
  742.     stack_sp = stack_base + oldmark;
  743.     retval = 0;
  744.     FREETMPS;
  745.     LEAVE;
  746.     }
  747.     return retval;
  748. }
  749.  
  750. /* Older forms, here grandfathered. */
  751.  
  752. #ifdef DEPRECATED
  753. I32
  754. perl_callargv(subname, spix, gimme, argv)
  755. char *subname;
  756. register I32 spix;    /* current stack pointer index */
  757. I32 gimme;        /* See G_* flags in cop.h */
  758. register char **argv;    /* null terminated arg list, NULL for no arglist */
  759. {
  760.     stack_sp = stack_base + spix;
  761.     return spix + perl_call_argv(subname, gimme, argv);
  762. }
  763.  
  764. I32
  765. perl_callpv(subname, spix, gimme, hasargs, numargs)
  766. char *subname;
  767. I32 spix;        /* stack pointer index after args are pushed */
  768. I32 gimme;        /* See G_* flags in cop.h */
  769. I32 hasargs;        /* whether to create a @_ array for routine */
  770. I32 numargs;        /* how many args are pushed on the stack */
  771. {
  772.     stack_sp = stack_base + spix;
  773.     PUSHMARK(stack_sp - numargs);
  774.     return spix - numargs + perl_call_sv((SV*)perl_get_cv(subname, TRUE),
  775.                 gimme, hasargs, numargs);
  776. }
  777.  
  778. I32
  779. perl_callsv(sv, spix, gimme, hasargs, numargs)
  780. SV* sv;
  781. I32 spix;        /* stack pointer index after args are pushed */
  782. I32 gimme;        /* See G_* flags in cop.h */
  783. I32 hasargs;        /* whether to create a @_ array for routine */
  784. I32 numargs;        /* how many args are pushed on the stack */
  785. {
  786.     stack_sp = stack_base + spix;
  787.     PUSHMARK(stack_sp - numargs);
  788.     return spix - numargs + perl_call_sv(sv, gimme, hasargs, numargs);
  789. }
  790. #endif
  791.  
  792. /* Require a module. */
  793.  
  794. void
  795. perl_requirepv(pv)
  796. char* pv;
  797. {
  798.     UNOP myop;        /* fake syntax tree node */
  799.     SV* sv;
  800.     dSP;
  801.  
  802.     ENTER;
  803.     SAVETMPS;
  804.     SAVESPTR(op);
  805.     sv = sv_newmortal();
  806.     sv_setpv(sv, pv);
  807.     op = (OP*)&myop;
  808.     Zero(op, 1, UNOP);
  809.     XPUSHs(sv);
  810.  
  811.     myop.op_type = OP_REQUIRE;
  812.     myop.op_next = Nullop;
  813.     myop.op_private = 1;
  814.     myop.op_flags = OPf_KNOW;
  815.  
  816.     PUTBACK;
  817.     if (op = pp_require())
  818.     run();
  819.     stack_sp--;
  820.     FREETMPS;
  821.     LEAVE;
  822. }
  823.  
  824. void
  825. magicname(sym,name,namlen)
  826. char *sym;
  827. char *name;
  828. I32 namlen;
  829. {
  830.     register GV *gv;
  831.  
  832.     if (gv = gv_fetchpv(sym,TRUE, SVt_PV))
  833.     sv_magic(GvSV(gv), (SV*)gv, 0, name, namlen);
  834. }
  835. #if defined(DOSISH)
  836. #    define PERLLIB_SEP ';'
  837. #elif defined(VMS)
  838. #    define PERLLIB_SEP '|'
  839. #elif defined(RISCOS)
  840. #    define PERLLIB_SEP ','
  841. #else
  842. #    define PERLLIB_SEP ':'
  843. #endif
  844.  
  845. static void
  846. incpush(p)
  847. char *p;
  848. {
  849.     char *s;
  850.  
  851.     if (!p)
  852.     return;
  853.  
  854.     /* Break at all separators */
  855.     while (*p) {
  856.     /* First, skip any consecutive separators */
  857.     while ( *p == PERLLIB_SEP ) {
  858.         /* Uncomment the next line for PATH semantics */
  859.         /* av_push(GvAVn(incgv), newSVpv(".", 1)); */
  860.         p++;
  861.     }
  862.     if ( (s = strchr(p, PERLLIB_SEP)) != Nullch ) {
  863.         av_push(GvAVn(incgv), newSVpv(p, (STRLEN)(s - p)));
  864.         p = s + 1;
  865.     } else {
  866.         av_push(GvAVn(incgv), newSVpv(p, 0));
  867.         break;
  868.     }
  869.     }
  870. }
  871.  
  872. /* This routine handles any switches that can be given during run */
  873.  
  874. char *
  875. moreswitches(s)
  876. char *s;
  877. {
  878.     I32 numlen;
  879.  
  880.     switch (*s) {
  881.     case '0':
  882.     nrschar = scan_oct(s, 4, &numlen);
  883.     nrs = savepvn("\n",1);
  884.     *nrs = nrschar;
  885.     if (nrschar > 0377) {
  886.         nrslen = 0;
  887.         nrs = "";
  888.     }
  889.     else if (!nrschar && numlen >= 2) {
  890.         nrslen = 2;
  891.         nrs = "\n\n";
  892.         nrschar = '\n';
  893.     }
  894.     return s + numlen;
  895.     case 'F':
  896.     minus_F = TRUE;
  897.     splitstr = savepv(s + 1);
  898.     s += strlen(s);
  899.     return s;
  900.     case 'a':
  901.     minus_a = TRUE;
  902.     s++;
  903.     return s;
  904.     case 'c':
  905.     minus_c = TRUE;
  906.     s++;
  907.     return s;
  908.     case 'd':
  909.     taint_not("-d");
  910.     if (!perldb) {
  911.         perldb = TRUE;
  912.         init_debugger();
  913.     }
  914.     s++;
  915.     return s;
  916.     case 'D':
  917. #ifdef DEBUGGING
  918.     taint_not("-D");
  919.     if (isALPHA(s[1])) {
  920.         static char debopts[] = "psltocPmfrxuLHXD";
  921.         char *d;
  922.  
  923.         for (s++; *s && (d = strchr(debopts,*s)); s++)
  924.         debug |= 1 << (d - debopts);
  925.     }
  926.     else {
  927.         debug = atoi(s+1);
  928.         for (s++; isDIGIT(*s); s++) ;
  929.     }
  930.     debug |= 0x80000000;
  931. #else
  932.     warn("Recompile perl with -DDEBUGGING to use -D switch\n");
  933.     for (s++; isALNUM(*s); s++) ;
  934. #endif
  935.     /*SUPPRESS 530*/
  936.     return s;
  937.     case 'i':
  938.     if (inplace)
  939.         Safefree(inplace);
  940.     inplace = savepv(s+1);
  941.     /*SUPPRESS 530*/
  942.     for (s = inplace; *s && !isSPACE(*s); s++) ;
  943.     *s = '\0';
  944.     break;
  945.     case 'I':
  946.     taint_not("-I");
  947.     if (*++s) {
  948.         char *e;
  949.         for (e = s; *e && !isSPACE(*e); e++) ;
  950.         av_push(GvAVn(incgv),newSVpv(s,e-s));
  951.         if (*e)
  952.         return e;
  953.     }
  954.     else
  955.         croak("No space allowed after -I");
  956.     break;
  957.     case 'l':
  958.     minus_l = TRUE;
  959.     s++;
  960.     if (ors)
  961.         Safefree(ors);
  962.     if (isDIGIT(*s)) {
  963.         ors = savepv("\n");
  964.         orslen = 1;
  965.         *ors = scan_oct(s, 3 + (*s == '0'), &numlen);
  966.         s += numlen;
  967.     }
  968.     else {
  969.         ors = savepvn(nrs,nrslen);
  970.         orslen = nrslen;
  971.     }
  972.     return s;
  973.     case 'n':
  974.     minus_n = TRUE;
  975.     s++;
  976.     return s;
  977.     case 'p':
  978.     minus_p = TRUE;
  979.     s++;
  980.     return s;
  981.     case 's':
  982.     taint_not("-s");
  983.     doswitches = TRUE;
  984.     s++;
  985.     return s;
  986.     case 'T':
  987.     tainting = TRUE;
  988.     s++;
  989.     return s;
  990.     case 'u':
  991.     do_undump = TRUE;
  992.     s++;
  993.     return s;
  994.     case 'U':
  995.     unsafe = TRUE;
  996.     s++;
  997.     return s;
  998.     case 'v':
  999.     printf("\nThis is perl, version %s\n\n",patchlevel);
  1000.     fputs("\nCopyright 1987-1994, Larry Wall\n",stdout);
  1001. #ifdef RISCOS
  1002.     fputs("\nRISC OS port by Luke Taylor 1995 (Release 1.5)\n",stdout);
  1003. #ifdef MSDOS
  1004.     fputs("MS-DOS port Copyright (c) 1989, 1990, Diomidis Spinellis\n",
  1005.     stdout);
  1006. #ifdef OS2
  1007.         fputs("OS/2 port Copyright (c) 1990, 1991, Raymond Chen, Kai Uwe Rommel\n",
  1008.         stdout);
  1009. #endif
  1010. #endif
  1011. #endif
  1012. #ifdef atarist
  1013.         fputs("atariST series port, ++jrb  bammi@cadence.com\n", stdout);
  1014. #endif
  1015.     fputs("\n\
  1016. Perl may be copied only under the terms of either the Artistic License or the\n\
  1017. GNU General Public License, which may be found in the Perl 5.0 source kit.\n",stdout);
  1018. #ifdef MSDOS
  1019.         usage(origargv[0]);
  1020. #endif
  1021.     exit(0);
  1022.     case 'w':
  1023.     dowarn = TRUE;
  1024.     s++;
  1025.     return s;
  1026.     case '*':
  1027.     case ' ':
  1028.     if (s[1] == '-')    /* Additional switches on #! line. */
  1029.         return s+2;
  1030.     break;
  1031.     case '-':
  1032.     case 0:
  1033.     case '\n':
  1034.     case '\t':
  1035.     break;
  1036.     case 'P':
  1037.     if (preprocess)
  1038.         return s+1;
  1039.     /* FALL THROUGH */
  1040.     default:
  1041.     croak("Can't emulate -%.1s on #! line",s);
  1042.     }
  1043.     return Nullch;
  1044. }
  1045.  
  1046. /* compliments of Tom Christiansen */
  1047.  
  1048. /* unexec() can be found in the Gnu emacs distribution */
  1049.  
  1050. void
  1051. my_unexec()
  1052. {
  1053. #ifdef UNEXEC
  1054.     int    status;
  1055.     extern int etext;
  1056.  
  1057.     sprintf (buf, "%s.perldump", origfilename);
  1058.     sprintf (tokenbuf, "%s/perl", BIN);
  1059.  
  1060.     status = unexec(buf, tokenbuf, &etext, sbrk(0), 0);
  1061.     if (status)
  1062.     fprintf(stderr, "unexec of %s into %s failed!\n", tokenbuf, buf);
  1063.     exit(status);
  1064. #else
  1065.     ABORT();        /* for use with undump */
  1066. #endif
  1067. }
  1068.  
  1069. static void
  1070. init_main_stash()
  1071. {
  1072.     GV *gv;
  1073.     curstash = defstash = newHV();
  1074.     curstname = newSVpv("main",4);
  1075.     gv = gv_fetchpv("main::",TRUE, SVt_PVHV);
  1076.     SvREFCNT_dec(GvHV(gv));
  1077.     GvHV(gv) = (HV*)SvREFCNT_inc(defstash);
  1078.     SvREADONLY_on(gv);
  1079.     HvNAME(defstash) = savepv("main");
  1080.     incgv = gv_HVadd(gv_AVadd(gv_fetchpv("INC",TRUE, SVt_PVAV)));
  1081.     SvMULTI_on(incgv);
  1082.     defgv = gv_fetchpv("_",TRUE, SVt_PVAV);
  1083.     curstash = defstash;
  1084.     compiling.cop_stash = defstash;
  1085.     debstash = GvHV(gv_fetchpv("DB::", GV_ADDMULTI, SVt_PVHV));
  1086. }
  1087.  
  1088. #ifdef CAN_PROTOTYPE
  1089. static void
  1090. open_script(char *scriptname, bool dosearch, SV *sv)
  1091. #else
  1092. static void
  1093. open_script(scriptname,dosearch,sv)
  1094. char *scriptname;
  1095. bool dosearch;
  1096. SV *sv;
  1097. #endif
  1098. {
  1099.     char *xfound = Nullch;
  1100.     char *xfailed = Nullch;
  1101.     register char *s;
  1102.     I32 len;
  1103.  
  1104.     if (dosearch && !strchr(scriptname, '/') && (s = getenv("PATH"))) {
  1105.  
  1106.     bufend = s + strlen(s);
  1107.     while (*s) {
  1108. #ifndef DOSISH
  1109.         s = cpytill(tokenbuf,s,bufend,':',&len);
  1110. #else
  1111. #ifdef atarist
  1112.         for (len = 0; *s && *s != ',' && *s != ';'; tokenbuf[len++] = *s++);
  1113.         tokenbuf[len] = '\0';
  1114. #else
  1115.         for (len = 0; *s && *s != ';'; tokenbuf[len++] = *s++);
  1116.         tokenbuf[len] = '\0';
  1117. #endif
  1118. #endif
  1119.         if (*s)
  1120.         s++;
  1121. #ifndef DOSISH
  1122.         if (len && tokenbuf[len-1] != '/')
  1123. #else
  1124. #ifdef atarist
  1125.         if (len && ((tokenbuf[len-1] != '\\') && (tokenbuf[len-1] != '/')))
  1126. #else
  1127.         if (len && tokenbuf[len-1] != '\\')
  1128. #endif
  1129. #endif
  1130.         (void)strcat(tokenbuf+len,"/");
  1131.         (void)strcat(tokenbuf+len,scriptname);
  1132.         DEBUG_p(fprintf(stderr,"Looking for %s\n",tokenbuf));
  1133.         if (Stat(tokenbuf,&statbuf) < 0)        /* not there? */
  1134.         continue;
  1135.         if (S_ISREG(statbuf.st_mode)
  1136.          && cando(S_IRUSR,TRUE,&statbuf) && cando(S_IXUSR,TRUE,&statbuf)) {
  1137.         xfound = tokenbuf;              /* bingo! */
  1138.         break;
  1139.         }
  1140.         if (!xfailed)
  1141.         xfailed = savepv(tokenbuf);
  1142.     }
  1143.     if (!xfound)
  1144.         croak("Can't execute %s", xfailed ? xfailed : scriptname );
  1145.     if (xfailed)
  1146.         Safefree(xfailed);
  1147.     scriptname = xfound;
  1148.     }
  1149.  
  1150.     origfilename = savepv(e_fp ? "-e" : scriptname);
  1151.     curcop->cop_filegv = gv_fetchfile(origfilename);
  1152.     if (strEQ(origfilename,"-"))
  1153.     scriptname = "";
  1154.     if (preprocess) {
  1155.     char *cpp = CPPSTDIN;
  1156.  
  1157.     if (strEQ(cpp,"cppstdin"))
  1158.         sprintf(tokenbuf, "%s/%s", SCRIPTDIR, cpp);
  1159.     else
  1160.         sprintf(tokenbuf, "%s", cpp);
  1161.     sv_catpv(sv,"-I");
  1162.     sv_catpv(sv,PRIVLIB_EXP);
  1163. #ifdef MSDOS
  1164.     (void)sprintf(buf, "\
  1165. sed %s -e \"/^[^#]/b\" \
  1166.  -e \"/^#[     ]*include[     ]/b\" \
  1167.  -e \"/^#[     ]*define[     ]/b\" \
  1168.  -e \"/^#[     ]*if[     ]/b\" \
  1169.  -e \"/^#[     ]*ifdef[     ]/b\" \
  1170.  -e \"/^#[     ]*ifndef[     ]/b\" \
  1171.  -e \"/^#[     ]*else/b\" \
  1172.  -e \"/^#[     ]*elif[     ]/b\" \
  1173.  -e \"/^#[     ]*undef[     ]/b\" \
  1174.  -e \"/^#[     ]*endif/b\" \
  1175.  -e \"s/^#.*//\" \
  1176.  %s | %s -C %s %s",
  1177.       (doextract ? "-e \"1,/^#/d\n\"" : ""),
  1178. #else
  1179.     (void)sprintf(buf, "\
  1180. %s %s -e '/^[^#]/b' \
  1181.  -e '/^#[     ]*include[     ]/b' \
  1182.  -e '/^#[     ]*define[     ]/b' \
  1183.  -e '/^#[     ]*if[     ]/b' \
  1184.  -e '/^#[     ]*ifdef[     ]/b' \
  1185.  -e '/^#[     ]*ifndef[     ]/b' \
  1186.  -e '/^#[     ]*else/b' \
  1187.  -e '/^#[     ]*elif[     ]/b' \
  1188.  -e '/^#[     ]*undef[     ]/b' \
  1189.  -e '/^#[     ]*endif/b' \
  1190.  -e 's/^[     ]*#.*//' \
  1191.  %s | %s -C %s %s",
  1192. #ifdef LOC_SED
  1193.       LOC_SED,
  1194. #else
  1195.       "sed",
  1196. #endif
  1197.       (doextract ? "-e '1,/^#/d\n'" : ""),
  1198. #endif
  1199.       scriptname, tokenbuf, SvPV(sv, na), CPPMINUS);
  1200.     doextract = FALSE;
  1201. #ifndef RISCOS
  1202. #ifdef IAMSUID                /* actually, this is caught earlier */
  1203.     if (euid != uid && !euid) {    /* if running suidperl */
  1204. #ifdef HAS_SETEUID
  1205.         (void)seteuid(uid);        /* musn't stay setuid root */
  1206. #else
  1207. #ifdef HAS_SETREUID
  1208.         (void)setreuid((Uid_t)-1, uid);
  1209. #else
  1210. #ifdef HAS_SETRESUID
  1211.         (void)setresuid((Uid_t)-1, uid, (Uid_t)-1);
  1212. #else
  1213.         setuid(uid);
  1214. #endif
  1215. #endif
  1216. #endif
  1217.         if (geteuid() != uid)
  1218.         croak("Can't do seteuid!\n");
  1219.     }
  1220. #endif /* IAMSUID */
  1221. #endif /* RISCOS */
  1222.     rsfp = my_popen(buf,"r");
  1223.     }
  1224.     else if (!*scriptname) {
  1225.     taint_not("program input from stdin");
  1226.     rsfp = stdin;
  1227.     }
  1228.     else
  1229.     rsfp = fopen(scriptname,"r");
  1230.     if ((FILE*)rsfp == Nullfp) {
  1231. #ifdef DOSUID
  1232. #ifndef IAMSUID        /* in case script is not readable before setuid */
  1233.     if (euid && Stat(SvPVX(GvSV(curcop->cop_filegv)),&statbuf) >= 0 &&
  1234.       statbuf.st_mode & (S_ISUID|S_ISGID)) {
  1235.         (void)sprintf(buf, "%s/sperl%s", BIN, patchlevel);
  1236.         execv(buf, origargv);    /* try again */
  1237.         croak("Can't do setuid\n");
  1238.     }
  1239. #endif
  1240. #endif
  1241.     croak("Can't open perl script \"%s\": %s\n",
  1242.       SvPVX(GvSV(curcop->cop_filegv)), Strerror(errno));
  1243.     }
  1244. }
  1245.  
  1246. #ifndef RISCOS
  1247. static void
  1248. validate_suid(validarg)
  1249. char *validarg;
  1250. {
  1251.     /* do we need to emulate setuid on scripts? */
  1252.  
  1253.     /* This code is for those BSD systems that have setuid #! scripts disabled
  1254.      * in the kernel because of a security problem.  Merely defining DOSUID
  1255.      * in perl will not fix that problem, but if you have disabled setuid
  1256.      * scripts in the kernel, this will attempt to emulate setuid and setgid
  1257.      * on scripts that have those now-otherwise-useless bits set.  The setuid
  1258.      * root version must be called suidperl or sperlN.NNN.  If regular perl
  1259.      * discovers that it has opened a setuid script, it calls suidperl with
  1260.      * the same argv that it had.  If suidperl finds that the script it has
  1261.      * just opened is NOT setuid root, it sets the effective uid back to the
  1262.      * uid.  We don't just make perl setuid root because that loses the
  1263.      * effective uid we had before invoking perl, if it was different from the
  1264.      * uid.
  1265.      *
  1266.      * DOSUID must be defined in both perl and suidperl, and IAMSUID must
  1267.      * be defined in suidperl only.  suidperl must be setuid root.  The
  1268.      * Configure script will set this up for you if you want it.
  1269.      */
  1270.  
  1271. #ifdef DOSUID
  1272.     char *s;
  1273.  
  1274.     if (Fstat(fileno(rsfp),&statbuf) < 0)    /* normal stat is insecure */
  1275.     croak("Can't stat script \"%s\"",origfilename);
  1276.     if (statbuf.st_mode & (S_ISUID|S_ISGID)) {
  1277.     I32 len;
  1278.  
  1279. #ifdef IAMSUID
  1280. #ifndef HAS_SETREUID
  1281.     /* On this access check to make sure the directories are readable,
  1282.      * there is actually a small window that the user could use to make
  1283.      * filename point to an accessible directory.  So there is a faint
  1284.      * chance that someone could execute a setuid script down in a
  1285.      * non-accessible directory.  I don't know what to do about that.
  1286.      * But I don't think it's too important.  The manual lies when
  1287.      * it says access() is useful in setuid programs.
  1288.      */
  1289.     if (access(SvPVX(GvSV(curcop->cop_filegv)),1))    /*double check*/
  1290.         croak("Permission denied");
  1291. #else
  1292.     /* If we can swap euid and uid, then we can determine access rights
  1293.      * with a simple stat of the file, and then compare device and
  1294.      * inode to make sure we did stat() on the same file we opened.
  1295.      * Then we just have to make sure he or she can execute it.
  1296.      */
  1297.     {
  1298.         struct stat tmpstatbuf;
  1299.  
  1300.         if (
  1301. #ifdef HAS_SETREUID
  1302.         setreuid(euid,uid) < 0
  1303. #else
  1304. # if HAS_SETRESUID
  1305.         setresuid(euid,uid,(Uid_t)-1) < 0
  1306. # endif
  1307. #endif
  1308.         || getuid() != euid || geteuid() != uid)
  1309.         croak("Can't swap uid and euid");    /* really paranoid */
  1310.         if (Stat(SvPVX(GvSV(curcop->cop_filegv)),&tmpstatbuf) < 0)
  1311.         croak("Permission denied");    /* testing full pathname here */
  1312.         if (tmpstatbuf.st_dev != statbuf.st_dev ||
  1313.         tmpstatbuf.st_ino != statbuf.st_ino) {
  1314.         (void)fclose(rsfp);
  1315.         if (rsfp = my_popen("/bin/mail root","w")) {    /* heh, heh */
  1316.             fprintf(rsfp,
  1317. "User %d tried to run dev %d ino %d in place of dev %d ino %d!\n\
  1318. (Filename of set-id script was %s, uid %d gid %d.)\n\nSincerely,\nperl\n",
  1319.             uid,tmpstatbuf.st_dev, tmpstatbuf.st_ino,
  1320.             statbuf.st_dev, statbuf.st_ino,
  1321.             SvPVX(GvSV(curcop->cop_filegv)),
  1322.             statbuf.st_uid, statbuf.st_gid);
  1323.             (void)my_pclose(rsfp);
  1324.         }
  1325.         croak("Permission denied\n");
  1326.         }
  1327.         if (
  1328. #ifdef HAS_SETREUID
  1329.               setreuid(uid,euid) < 0
  1330. #else
  1331. # if defined(HAS_SETRESUID)
  1332.               setresuid(uid,euid,(Uid_t)-1) < 0
  1333. # endif
  1334. #endif
  1335.               || getuid() != uid || geteuid() != euid)
  1336.         croak("Can't reswap uid and euid");
  1337.         if (!cando(S_IXUSR,FALSE,&statbuf))        /* can real uid exec? */
  1338.         croak("Permission denied\n");
  1339.     }
  1340. #endif /* HAS_SETREUID */
  1341. #endif /* IAMSUID */
  1342.  
  1343.     if (!S_ISREG(statbuf.st_mode))
  1344.         croak("Permission denied");
  1345.     if (statbuf.st_mode & S_IWOTH)
  1346.         croak("Setuid/gid script is writable by world");
  1347.     doswitches = FALSE;        /* -s is insecure in suid */
  1348.     curcop->cop_line++;
  1349.     if (fgets(tokenbuf,sizeof tokenbuf, rsfp) == Nullch ||
  1350.       strnNE(tokenbuf,"#!",2) )    /* required even on Sys V */
  1351.         croak("No #! line");
  1352.     s = tokenbuf+2;
  1353.     if (*s == ' ') s++;
  1354.     while (!isSPACE(*s)) s++;
  1355.     if (strnNE(s-4,"perl",4) && strnNE(s-9,"perl",4))  /* sanity check */
  1356.         croak("Not a perl script");
  1357.     while (*s == ' ' || *s == '\t') s++;
  1358.     /*
  1359.      * #! arg must be what we saw above.  They can invoke it by
  1360.      * mentioning suidperl explicitly, but they may not add any strange
  1361.      * arguments beyond what #! says if they do invoke suidperl that way.
  1362.      */
  1363.     len = strlen(validarg);
  1364.     if (strEQ(validarg," PHOOEY ") ||
  1365.         strnNE(s,validarg,len) || !isSPACE(s[len]))
  1366.         croak("Args must match #! line");
  1367.  
  1368. #ifndef IAMSUID
  1369.     if (euid != uid && (statbuf.st_mode & S_ISUID) &&
  1370.         euid == statbuf.st_uid)
  1371.         if (!do_undump)
  1372.         croak("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
  1373. FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
  1374. #endif /* IAMSUID */
  1375.  
  1376.     if (euid) {    /* oops, we're not the setuid root perl */
  1377.         (void)fclose(rsfp);
  1378. #ifndef IAMSUID
  1379.         (void)sprintf(buf, "%s/sperl%s", BIN, patchlevel);
  1380.         execv(buf, origargv);    /* try again */
  1381. #endif
  1382.         croak("Can't do setuid\n");
  1383.     }
  1384.  
  1385.     if (statbuf.st_mode & S_ISGID && statbuf.st_gid != egid) {
  1386. #ifdef HAS_SETEGID
  1387.         (void)setegid(statbuf.st_gid);
  1388. #else
  1389. #ifdef HAS_SETREGID
  1390.            (void)setregid((Gid_t)-1,statbuf.st_gid);
  1391. #else
  1392. #ifdef HAS_SETRESGID
  1393.            (void)setresgid((Gid_t)-1,statbuf.st_gid,(Gid_t)-1);
  1394. #else
  1395.         setgid(statbuf.st_gid);
  1396. #endif
  1397. #endif
  1398. #endif
  1399.         if (getegid() != statbuf.st_gid)
  1400.         croak("Can't do setegid!\n");
  1401.     }
  1402.     if (statbuf.st_mode & S_ISUID) {
  1403.         if (statbuf.st_uid != euid)
  1404. #ifdef HAS_SETEUID
  1405.         (void)seteuid(statbuf.st_uid);    /* all that for this */
  1406. #else
  1407. #ifdef HAS_SETREUID
  1408.                 (void)setreuid((Uid_t)-1,statbuf.st_uid);
  1409. #else
  1410. #ifdef HAS_SETRESUID
  1411.                 (void)setresuid((Uid_t)-1,statbuf.st_uid,(Uid_t)-1);
  1412. #else
  1413.         setuid(statbuf.st_uid);
  1414. #endif
  1415. #endif
  1416. #endif
  1417.         if (geteuid() != statbuf.st_uid)
  1418.         croak("Can't do seteuid!\n");
  1419.     }
  1420.     else if (uid) {            /* oops, mustn't run as root */
  1421. #ifdef HAS_SETEUID
  1422.           (void)seteuid((Uid_t)uid);
  1423. #else
  1424. #ifdef HAS_SETREUID
  1425.           (void)setreuid((Uid_t)-1,(Uid_t)uid);
  1426. #else
  1427. #ifdef HAS_SETRESUID
  1428.           (void)setresuid((Uid_t)-1,(Uid_t)uid,(Uid_t)-1);
  1429. #else
  1430.           setuid((Uid_t)uid);
  1431. #endif
  1432. #endif
  1433. #endif
  1434.         if (geteuid() != uid)
  1435.         croak("Can't do seteuid!\n");
  1436.     }
  1437.     init_ids();
  1438.     if (!cando(S_IXUSR,TRUE,&statbuf))
  1439.         croak("Permission denied\n");    /* they can't do this */
  1440.     }
  1441. #ifdef IAMSUID
  1442.     else if (preprocess)
  1443.     croak("-P not allowed for setuid/setgid script\n");
  1444.     else
  1445.     croak("Script is not setuid/setgid in suidperl\n");
  1446. #endif /* IAMSUID */
  1447. #else /* !DOSUID */
  1448.     if (euid != uid || egid != gid) {    /* (suidperl doesn't exist, in fact) */
  1449. #ifndef SETUID_SCRIPTS_ARE_SECURE_NOW
  1450.     Fstat(fileno(rsfp),&statbuf);    /* may be either wrapped or real suid */
  1451.     if ((euid != uid && euid == statbuf.st_uid && statbuf.st_mode & S_ISUID)
  1452.         ||
  1453.         (egid != gid && egid == statbuf.st_gid && statbuf.st_mode & S_ISGID)
  1454.        )
  1455.         if (!do_undump)
  1456.         croak("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
  1457. FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
  1458. #endif /* SETUID_SCRIPTS_ARE_SECURE_NOW */
  1459.     /* not set-id, must be wrapped */
  1460.     }
  1461. #endif /* DOSUID */
  1462. }
  1463. #endif
  1464.  
  1465. static void
  1466. find_beginning()
  1467. {
  1468.     register char *s;
  1469.  
  1470.     /* skip forward in input to the real script? */
  1471.  
  1472.     taint_not("-x");
  1473.     while (doextract) {
  1474.     if ((s = sv_gets(linestr, rsfp, 0)) == Nullch)
  1475.         croak("No Perl script found in input\n");
  1476.     if (*s == '#' && s[1] == '!' && instr(s,"perl")) {
  1477.         ungetc('\n',rsfp);        /* to keep line count right */
  1478.         doextract = FALSE;
  1479.         if (s = instr(s,"perl -")) {
  1480.         s += 6;
  1481.         /*SUPPRESS 530*/
  1482.         while (s = moreswitches(s)) ;
  1483.         }
  1484.         if (cddir && chdir(cddir) < 0)
  1485.         croak("Can't chdir to %s",cddir);
  1486.     }
  1487.     }
  1488. }
  1489.  
  1490. static void
  1491. init_ids()
  1492. {
  1493. #ifndef RISCOS
  1494.     uid = (int)getuid();
  1495.     euid = (int)geteuid();
  1496.     gid = (int)getgid();
  1497.     egid = (int)getegid();
  1498. #ifdef VMS
  1499.     uid |= gid << 16;
  1500.     euid |= egid << 16;
  1501. #endif
  1502.     tainting |= (euid != uid || egid != gid);
  1503. #endif
  1504. }
  1505.  
  1506. static void
  1507. init_debugger()
  1508. {
  1509.     curstash = debstash;
  1510.     dbargs = GvAV(gv_AVadd((gv_fetchpv("args", GV_ADDMULTI, SVt_PVAV))));
  1511.     AvREAL_off(dbargs);
  1512.     DBgv = gv_fetchpv("DB", GV_ADDMULTI, SVt_PVGV);
  1513.     DBline = gv_fetchpv("dbline", GV_ADDMULTI, SVt_PVAV);
  1514.     DBsub = gv_HVadd(gv_fetchpv("sub", GV_ADDMULTI, SVt_PVHV));
  1515.     DBsingle = GvSV((gv_fetchpv("single", GV_ADDMULTI, SVt_PV)));
  1516.     DBtrace = GvSV((gv_fetchpv("trace", GV_ADDMULTI, SVt_PV)));
  1517.     DBsignal = GvSV((gv_fetchpv("signal", GV_ADDMULTI, SVt_PV)));
  1518.     curstash = defstash;
  1519. }
  1520.  
  1521. static void
  1522. init_stacks()
  1523. {
  1524.     stack = newAV();
  1525.     mainstack = stack;            /* remember in case we switch stacks */
  1526.     AvREAL_off(stack);            /* not a real array */
  1527.     av_extend(stack,127);
  1528.  
  1529.     stack_base = AvARRAY(stack);
  1530.     stack_sp = stack_base;
  1531.     stack_max = stack_base + 127;
  1532.  
  1533.     New(54,markstack,64,I32);
  1534.     markstack_ptr = markstack;
  1535.     markstack_max = markstack + 64;
  1536.  
  1537.     New(54,scopestack,32,I32);
  1538.     scopestack_ix = 0;
  1539.     scopestack_max = 32;
  1540.  
  1541.     New(54,savestack,128,ANY);
  1542.     savestack_ix = 0;
  1543.     savestack_max = 128;
  1544.  
  1545.     New(54,retstack,16,OP*);
  1546.     retstack_ix = 0;
  1547.     retstack_max = 16;
  1548.  
  1549.     New(50,cxstack,128,CONTEXT);
  1550.     cxstack_ix    = -1;
  1551.     cxstack_max    = 128;
  1552.  
  1553.     New(50,tmps_stack,128,SV*);
  1554.     tmps_ix = -1;
  1555.     tmps_max = 128;
  1556.  
  1557.     DEBUG( {
  1558.     New(51,debname,128,char);
  1559.     New(52,debdelim,128,char);
  1560.     } )
  1561. }
  1562.  
  1563. static FILE *tmpfp;  /* moved outside init_lexer() because of UNICOS bug */
  1564. static void
  1565. init_lexer()
  1566. {
  1567.     tmpfp = rsfp;
  1568.  
  1569.     lex_start(linestr);
  1570.     rsfp = tmpfp;
  1571.     subname = newSVpv("main",4);
  1572. }
  1573.  
  1574. static void
  1575. init_predump_symbols()
  1576. {
  1577.     GV *tmpgv;
  1578.     GV *othergv;
  1579.  
  1580.     sv_setpvn(GvSV(gv_fetchpv("\"", TRUE, SVt_PV)), " ", 1);
  1581.  
  1582.     stdingv = gv_fetchpv("STDIN",TRUE, SVt_PVIO);
  1583.     SvMULTI_on(stdingv);
  1584.     IoIFP(GvIOp(stdingv)) = stdin;
  1585.     tmpgv = gv_fetchpv("stdin",TRUE, SVt_PV);
  1586.     GvIOp(tmpgv) = (IO*)SvREFCNT_inc(GvIOp(stdingv));
  1587.     SvMULTI_on(tmpgv);
  1588.  
  1589.     tmpgv = gv_fetchpv("STDOUT",TRUE, SVt_PVIO);
  1590.     SvMULTI_on(tmpgv);
  1591.     IoOFP(GvIOp(tmpgv)) = IoIFP(GvIOp(tmpgv)) = stdout;
  1592.     defoutgv = tmpgv;
  1593.     tmpgv = gv_fetchpv("stdout",TRUE, SVt_PV);
  1594.     GvIOp(tmpgv) = (IO*)SvREFCNT_inc(GvIOp(defoutgv));
  1595.     SvMULTI_on(tmpgv);
  1596.  
  1597.     othergv = gv_fetchpv("STDERR",TRUE, SVt_PVIO);
  1598.     SvMULTI_on(othergv);
  1599.     IoOFP(GvIOp(othergv)) = IoIFP(GvIOp(othergv)) = stderr;
  1600.     tmpgv = gv_fetchpv("stderr",TRUE, SVt_PV);
  1601.     GvIOp(tmpgv) = (IO*)SvREFCNT_inc(GvIOp(othergv));
  1602.     SvMULTI_on(tmpgv);
  1603.  
  1604.     statname = NEWSV(66,0);        /* last filename we did stat on */
  1605. }
  1606.  
  1607. static void
  1608. init_postdump_symbols(argc,argv,env)
  1609. register int argc;
  1610. register char **argv;
  1611. register char **env;
  1612. {
  1613.     char *s;
  1614.     SV *sv;
  1615.     GV* tmpgv;
  1616.  
  1617.     argc--,argv++;    /* skip name of script */
  1618.     if (doswitches) {
  1619.     for (; argc > 0 && **argv == '-'; argc--,argv++) {
  1620.         if (!argv[0][1])
  1621.         break;
  1622.         if (argv[0][1] == '-') {
  1623.         argc--,argv++;
  1624.         break;
  1625.         }
  1626.         if (s = strchr(argv[0], '=')) {
  1627.         *s++ = '\0';
  1628.         sv_setpv(GvSV(gv_fetchpv(argv[0]+1,TRUE, SVt_PV)),s);
  1629.         }
  1630.         else
  1631.         sv_setiv(GvSV(gv_fetchpv(argv[0]+1,TRUE, SVt_PV)),1);
  1632.     }
  1633.     }
  1634.     toptarget = NEWSV(0,0);
  1635.     sv_upgrade(toptarget, SVt_PVFM);
  1636.     sv_setpvn(toptarget, "", 0);
  1637.     bodytarget = NEWSV(0,0);
  1638.     sv_upgrade(bodytarget, SVt_PVFM);
  1639.     sv_setpvn(bodytarget, "", 0);
  1640.     formtarget = bodytarget;
  1641.  
  1642.     tainted = 1;
  1643.     if (tmpgv = gv_fetchpv("0",TRUE, SVt_PV)) {
  1644.     sv_setpv(GvSV(tmpgv),origfilename);
  1645.     magicname("0", "0", 1);
  1646.     }
  1647.     if (tmpgv = gv_fetchpv("\024",TRUE, SVt_PV))
  1648.     time(&basetime);
  1649.     if (tmpgv = gv_fetchpv("\030",TRUE, SVt_PV))
  1650.     sv_setpv(GvSV(tmpgv),origargv[0]);
  1651.     if (argvgv = gv_fetchpv("ARGV",TRUE, SVt_PVAV)) {
  1652.     SvMULTI_on(argvgv);
  1653.     (void)gv_AVadd(argvgv);
  1654.     av_clear(GvAVn(argvgv));
  1655.     for (; argc > 0; argc--,argv++) {
  1656.         av_push(GvAVn(argvgv),newSVpv(argv[0],0));
  1657.     }
  1658.     }
  1659.     if (envgv = gv_fetchpv("ENV",TRUE, SVt_PVHV)) {
  1660.     HV *hv;
  1661.     SvMULTI_on(envgv);
  1662.     hv = GvHVn(envgv);
  1663.     hv_clear(hv);
  1664. #if !defined(VMS) && !defined(RISCOS)  /* VMS doesn't have environ array */
  1665.     if (env != environ) {
  1666.         environ[0] = Nullch;
  1667.         hv_magic(hv, envgv, 'E');
  1668.     }
  1669. #endif
  1670. #ifdef DYNAMIC_ENV_FETCH
  1671.     HvNAME(hv) = savepv(ENV_HV_NAME);
  1672. #endif
  1673.     for (; *env; env++) {
  1674.         if (!(s = strchr(*env,'=')))
  1675.         continue;
  1676.         *s++ = '\0';
  1677.         sv = newSVpv(s--,0);
  1678.         sv_magic(sv, sv, 'e', *env, s - *env);
  1679.         (void)hv_store(hv, *env, s - *env, sv, 0);
  1680.         *s = '=';
  1681.     }
  1682.     hv_magic(hv, envgv, 'E');
  1683.     }
  1684.     tainted = 0;
  1685. #ifndef RISCOS  /* OK ???*/
  1686.     if (tmpgv = gv_fetchpv("$",TRUE, SVt_PV))
  1687.     sv_setiv(GvSV(tmpgv),(I32)getpid());
  1688. #endif
  1689.  
  1690. }
  1691.  
  1692. static void
  1693. init_perllib()
  1694. {
  1695.     char *s;
  1696.     if (!tainting) {
  1697.     s = getenv("PERL5LIB");
  1698.     if (s)
  1699.         incpush(s);
  1700.     else
  1701.         incpush(getenv("PERLLIB"));
  1702.     }
  1703.  
  1704. #ifdef ARCHLIB_EXP
  1705.     incpush(ARCHLIB_EXP);
  1706. #endif
  1707. #ifndef PRIVLIB_EXP
  1708. #define PRIVLIB_EXP "/usr/local/lib/perl5:/usr/local/lib/perl"
  1709. #endif
  1710.     incpush(PRIVLIB_EXP);
  1711.  
  1712.     av_push(GvAVn(incgv),newSVpv(".",1));
  1713. }
  1714.  
  1715. void
  1716. calllist(list)
  1717. AV* list;
  1718. {
  1719.     jmp_buf oldtop;
  1720.     STRLEN len;
  1721.     line_t oldline = curcop->cop_line;
  1722.  
  1723.     Copy(top_env, oldtop, 1, jmp_buf);
  1724.  
  1725.     while (AvFILL(list) >= 0) {
  1726.     CV *cv = (CV*)av_shift(list);
  1727.  
  1728.     SAVEFREESV(cv);
  1729.  
  1730.     switch (setjmp(top_env)) {
  1731.     case 0: {
  1732.         SV* atsv = GvSV(gv_fetchpv("@",TRUE, SVt_PV));
  1733.         PUSHMARK(stack_sp);
  1734.         perl_call_sv((SV*)cv, G_EVAL|G_DISCARD);
  1735.         (void)SvPV(atsv, len);
  1736.         if (len) {
  1737.             Copy(oldtop, top_env, 1, jmp_buf);
  1738.             curcop = &compiling;
  1739.             curcop->cop_line = oldline;
  1740.             if (list == beginav)
  1741.             sv_catpv(atsv, "BEGIN failed--compilation aborted");
  1742.             else
  1743.             sv_catpv(atsv, "END failed--cleanup aborted");
  1744.             croak("%s", SvPVX(atsv));
  1745.         }
  1746.         }
  1747.         break;
  1748.     case 1:
  1749. #ifdef VMS
  1750.         statusvalue = 255;    /* XXX I don't think we use 1 anymore. */
  1751. #else
  1752.     statusvalue = 1;
  1753. #endif
  1754.         /* FALL THROUGH */
  1755.     case 2:
  1756.         /* my_exit() was called */
  1757.         curstash = defstash;
  1758.         if (endav)
  1759.         calllist(endav);
  1760.         FREETMPS;
  1761.         Copy(oldtop, top_env, 1, jmp_buf);
  1762.         curcop = &compiling;
  1763.         curcop->cop_line = oldline;
  1764.         if (statusvalue) {
  1765.         if (list == beginav)
  1766.             croak("BEGIN failed--compilation aborted");
  1767.         else
  1768.             croak("END failed--cleanup aborted");
  1769.         }
  1770.         my_exit(statusvalue);
  1771.         /* NOTREACHED */
  1772.         return;
  1773.     case 3:
  1774.         if (!restartop) {
  1775.         fprintf(stderr, "panic: restartop\n");
  1776.         FREETMPS;
  1777.         break;
  1778.         }
  1779.         Copy(oldtop, top_env, 1, jmp_buf);
  1780.         curcop = &compiling;
  1781.         curcop->cop_line = oldline;
  1782.         longjmp(top_env, 3);
  1783.     }
  1784.     }
  1785.  
  1786.     Copy(oldtop, top_env, 1, jmp_buf);
  1787. }
  1788.  
  1789.